package gohttp

import (
	"flag"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/go-micro/plugins/v4/registry/consul"
	"github.com/go-micro/plugins/v4/registry/nacos"
	"github.com/go-micro/plugins/v4/server/http"
	config "go-micro-framework/go_service/core/cofig"
	"go-micro-framework/go_service/core/gohandler"
	"go-micro.dev/v4"
	"go-micro.dev/v4/logger"
	"go-micro.dev/v4/registry"
	"go-micro.dev/v4/server"
	"io"
	"log"
	"net"
	"os"
	"reflect"
)

//func option() *registry.Options {
//	optiones := registry.Options{Addrs: []string{"192.168.2.201:8500"}}
//	return &optiones
//}

var configFile = flag.String("config", "./bbs-go.yaml", "配置文件路径")

type StartService struct {
	ServerName    string   // "go.micro.srv.GetUserInfo"
	ServerPort    string   //"8080"
	Version       string   //latest
	ConfigFile    string   //configFile 参考
	NacosAddress  []string //"192.168.2.201:8848"
	ConsulAddress []string //"192.168.2.201:8500"
	HandlerEntity gohandler.HandlerEntity
	InitRequest   InitRequestInterface
}

func StartHttpService(start *StartService) {
	if start == nil {
		logger.Error("启动失败，StartService 对象不能为空 start:[nil]")
		return
	}

	// 初始化配置
	conf := config.Init(start.ConfigFile)
	// 初始化日志
	if file, err := os.OpenFile(conf.Service.LogFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666); err == nil {
		log.SetOutput(io.MultiWriter(os.Stdout, file))
	} else {
		log.SetOutput(os.Stdout)
		log.Print(err)
	}
	var serverRegistry registry.Registry
	//var consulRegistry registry.Registry
	//var registryOK bool = bool(false)
	if start.NacosAddress != nil {
		serverRegistry = nacos.NewRegistry(func(options *registry.Options) {
			options.Addrs = start.NacosAddress
		})
		if serverRegistry != nil {
			fmt.Println("nacosRegistry Address", start.NacosAddress)
		}
	}
	if start.ConsulAddress != nil {
		serverRegistry = consul.NewRegistry(
			registry.Addrs(start.NacosAddress...),
		)
		if serverRegistry != nil {
			fmt.Println("consulRegistry", serverRegistry)
		}

	}

	address := fmt.Sprintf(":%s", start.ServerPort)
	httpServer := http.NewServer(
		server.Name(start.ServerName),
		server.Address(address),
	)
	// Create service
	service := micro.NewService(
		micro.Server(httpServer),
		micro.Name(start.ServerName),
		micro.Version(start.Version),
		//micro.Registry(serverRegistry),
	)
	micro.RegisterHandler(service.Server(), service)
	// 设置日志级别为信息级别
	logger.DefaultLogger.Log(logger.DebugLevel)

	gin.SetMode(gin.DebugMode)
	router := gin.Default()
	var ex = &start.HandlerEntity
	router.Use(gohandler.GinLoggerHandler(ex),
		gohandler.GinWhiteHandler(ex),
		gohandler.GinBlackHandler(ex),
		gohandler.GinUserActionHandler(ex),
		gohandler.GinTokenHandler(ex),
		gohandler.GinParameterMd5SignHandler(ex),
		gohandler.GinParameterHandler(ex),
		gohandler.GinVersionHandler(ex))

	//router service router
	//register Default router
	if start.InitRequest != nil {
		//初始化用户自定义接口到拦截器和初始化用户自定义接口白名单信息
		start.InitRequest.InitRequestMapping()
	}
	var sys = SystemDefaultInitRequest{}
	//初始化用户自定义接口到拦截器和初始化用户自定义接口白名单信息
	sys.InitRequestMapping()
	//注册用户自定义接口到路由中和接口白名单缓存，和接口接收参数检验对象缓存
	registerRouteMappingWhiteRequestEntity(router)
	handler := service.Server().NewHandler(router)
	service.Server().Handle(handler)
	service.Server().Init()
	GetServiceIpAddress(start.ServerPort)
	if err := service.Run(); err != nil {
		logger.Fatal(err)
	}
}

func registerRouteMappingWhiteRequestEntity(router *gin.Engine) {
	// 使用 Range 遍历 RouteManagers 对象
	for _, request := range GetRequestMapping() {
		if request.RequestVo != nil {
			gohandler.AddUrlHttpRequestEntityCache(request.Path, request.RequestVo)
		}
		if request.Remote != nil {
			request.Remote.Url = request.Path
			gohandler.AddUrlSysWhiteRemoteCache(request.Remote)
		}
		RouterMethodProxy(router, request.Method, request.Path, request.Handlers)
		//switch request.Method {
		//case nethttp.MethodGet:
		//	router.GET(request.Path, request.Handlers)
		//	break
		//case nethttp.MethodPost:
		//	router.POST(request.Path, request.Handlers)
		//	break
		//case nethttp.MethodPut:
		//	router.PUT(request.Path, request.Handlers)
		//	break
		//case nethttp.MethodHead:
		//	router.HEAD(request.Path, request.Handlers)
		//	break
		//case nethttp.MethodPatch:
		//	router.PATCH(request.Path, request.Handlers)
		//	break
		//case nethttp.MethodDelete:
		//	router.DELETE(request.Path, request.Handlers)
		//	break
		//case nethttp.MethodOptions:
		//	router.OPTIONS(request.Path, request.Handlers)
		//	break
		//default:
		//	router.POST(request.Path, request.Handlers)
		//}

	}

}

/** 通过策略模式获取对应的操作对象 **/
func RouterMethodProxy(router *gin.Engine, methodByName, path string, Handlers gin.HandlerFunc) {
	if "TRACE" == methodByName || "CONNECT" == methodByName {
		methodByName = "POST"
	}
	var values []reflect.Value
	values = append(values, reflect.ValueOf(path))
	values = append(values, reflect.ValueOf(Handlers))
	/** 通过策略模式获取对应的操作对象 **/
	entity := reflect.ValueOf(router)
	entity.MethodByName(methodByName).Call(values)
}

func ValueOf(args ...interface{}) []reflect.Value {
	var values []reflect.Value
	for _, arg := range args {
		if strs, ok := arg.([]string); ok {
			for _, str := range strs {
				values = append(values, reflect.ValueOf(str))
			}
		} else {
			values = append(values, reflect.ValueOf(arg))
		}

	}
	return values
}

func GetServiceIpAddress(port string) {
	// 获取本机所有网络接口信息
	interfaces, err := net.Interfaces()
	if err != nil {
		fmt.Println("Failed to get network interfaces:", err)
		return
	}

	// 遍历接口信息，找到启动的IP地址
	for _, iface := range interfaces {
		// 排除非物理接口和回环接口
		if iface.Flags&net.FlagUp == 0 || iface.Flags&net.FlagLoopback != 0 {
			continue
		}

		// 获取接口的IP地址信息
		addrs, err := iface.Addrs()
		if err != nil {
			fmt.Println("Failed to get addresses for interface", iface.Name, ":", err)
			continue
		}

		// 遍历IP地址信息，找到IPv4或IPv6地址
		for _, addr := range addrs {
			ipNet, ok := addr.(*net.IPNet)
			if !ok || ipNet.IP.IsLoopback() {
				continue
			}

			// 判断IP地址类型为IPv4或IPv6
			ip := ipNet.IP
			if ip.To4() != nil {
				address := fmt.Sprintf("%s:%s", ip, port)
				fmt.Println("IPv4 address:", address)
			} else if ip.To16() != nil {
				address := fmt.Sprintf("%s:%s", ip, port)
				fmt.Println("IPv6 address:", address)
			}
		}
	}
}
